#region Copyright
/// <copyright>
/// Copyright (c) 2007 Ilia Shramko.
/// Released under the terms of the GNU General Public License.
/// </copyright>
#endregion

using System;
using System.Collections.Generic;
using System.Text;

namespace Osh.Teletext
{
	public struct CharPosition : IComparable, IComparable<CharPosition>, IEquatable<CharPosition>
	{
		public static CharPosition TopLeft;

		public const int MinRowNumber = 0;
		public const int MaxRowNumber = 24;
		public const int MaxRows = 25;

		public const int MinColumnNumber = 0;
		public const int MaxColumnNumber = 39;
		public const int MaxColumns = 40;

		private byte _row;
		private byte _column;

		public CharPosition(int row, int column)
		{
			if(row < MinRowNumber || row > MaxRowNumber)
				throw new ArgumentOutOfRangeException("row");
			if(column < MinColumnNumber || column > MaxColumnNumber)
				throw new ArgumentOutOfRangeException("column");

			_row = (byte)row;
			_column = (byte)column;
		}

		public int Row
		{
			get { return _row; }
			set
			{
				if(value < MinRowNumber || value > MaxRowNumber)
					throw new ArgumentOutOfRangeException("Row");
				_row = (byte)value;
			}
		}

		public int Column
		{
			get { return _column; }
			set
			{
				if(value < MinColumnNumber || value > MaxColumnNumber)
					throw new ArgumentOutOfRangeException("Column");
				_column = (byte)value;
			}
		}

		public override string ToString()
		{
			return "{" + _row.ToString() + "," + _column.ToString() + "}";
		}

		#region IComparable Members & Stuff
		public int CompareTo(object obj)
		{
			return this.GetHashCode().CompareTo(((CharPosition)obj).GetHashCode());
		}

		public override int GetHashCode()
		{
			return (_row << 8) | _column;
		}

		public override bool Equals(object obj)
		{
			if(obj == null)
				return false;

			if(!(obj is CharPosition))
				return false;

			return this.CompareTo(obj) == 0;
		}

		public bool Equals(CharPosition obj)
		{
			if((object)obj == null)
				return false;

			return this.CompareTo(obj) == 0;
		}

		public static bool operator ==(CharPosition a, CharPosition b)
		{
			if(object.ReferenceEquals(a, b))
				return true;

			if(((object)a == null) || ((object)b == null))
				return false;

			return a.Equals(b);
		}

		public static bool operator !=(CharPosition a, CharPosition b)
		{
			return !(a == b);
		}
		#endregion IComparable Members & Stuff
		
		#region IComparable<CharPosition> Members
		public int CompareTo(CharPosition other)
		{
			return this.CompareTo((object)other);
		}
		#endregion

		#region IEquatable<CharPosition> Members
		bool IEquatable<CharPosition>.Equals(CharPosition other)
		{
			return this.Equals(other);
		}
		#endregion
	}

}
